package ro.isdc.training.jpa.systemuser.domain;

import java.util.List;

import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;

import org.apache.commons.lang.builder.ToStringBuilder;

import ro.isdc.training.jpa.misc.domain.BusinessEntity;
import org.apache.commons.lang.builder.ToStringStyle;

/**
 * The System User entity
 * 
 * Remark: creationTimestamp and lastUpdateTimestamp from BusinessEntity
 * mapped superclass apply in the context of this entity. The column have the
 * same name as the fields so NO @AttributeOverride annotation is required
 * 
 * @author Andrei Chirila
 */
@javax.persistence.Entity
@Table(name = "SYSTEM_USERS")
@AttributeOverrides( {
		@AttributeOverride(name = "entityId", column = @Column(name = "USERID")),
		@AttributeOverride(name = "versionNo", column = @Column(name = "USERVERSNO")), })
public class SystemUser extends BusinessEntity {

	/**
	 * Generated Serial Version UID
	 */
	private static final long serialVersionUID = 8366219103344898793L;

	/**
	 * The username
	 */
	private String username;

	/**
	 * The password
	 */
	private String password;

	/**
	 * Is the user still active or not?
	 */
	private boolean isDeleted = false;

	/**
	 * The roles the user has
	 */
	@OneToMany(cascade = { CascadeType.ALL })
	@JoinColumn(name = "USERID")
	private List<SystemUserRole> roles;

	/**
	 * @return the username
	 */
	public String getUsername() {
		return username;
	}

	/**
	 * @param username
	 *          the username to set
	 */
	public void setUsername(final String username) {
		this.username = username;
	}

	/**
	 * @return the password
	 */
	public String getPassword() {
		return password;
	}

	/**
	 * @param password
	 *          the password to set
	 */
	public void setPassword(final String password) {
		this.password = password;
	}

	/**
	 * @return the isDeleted
	 */
	public boolean isDeleted() {
		return isDeleted;
	}

	/**
	 * @param isDeleted
	 *          the isDeleted to set
	 */
	public void setDeleted(final boolean isDeleted) {
		this.isDeleted = isDeleted;
	}

	/**
	 * @param roles
	 *          the roles to set
	 */
	public void setRoles(final List<SystemUserRole> roles) {
		this.roles = roles;
	}

	/**
	 * @return the roles
	 */
	public List<SystemUserRole> getRoles() {
		return roles;
	}

	/**
	 * @return true if the user is an administrator
	 */
	public boolean isAdmin() {
		if (roles == null || roles.isEmpty()) {
			return false;
		}

		for (SystemUserRole role : roles) {
			if (UserRole.ROLE_ADMIN.equals(role.getRolename())) {
				return true;
			}
		}

		return false;
	}

	/**
	 * @return true if the user is a professor
	 */
	public boolean isProfessor() {
		if (roles == null || roles.isEmpty()) {
			return false;
		}

		for (SystemUserRole role : roles) {
			if (UserRole.ROLE_PROFESSOR.equals(role.getRolename())) {
				return true;
			}
		}

		return false;
	}

	/**
	 * @return true if the user is a student
	 */
	public boolean isStudent() {
		if (roles == null || roles.isEmpty()) {
			return false;
		}

		for (SystemUserRole role : roles) {
			if (UserRole.ROLE_STUDENT.equals(role.getRolename())) {
				return true;
			}
		}

		return false;
	}

	/**
	 * @see java.lang.Object#toString() Exclude collections that are lazily loaded
	 *      to avoid LazyInitializationException/PersistenceException in domain.
	 */
	public String toString() {
		return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).append(
				"username", this.username).append("entityId", this.entityId).append(
				"isDeleted", this.isDeleted).append("password", this.password).append(
				"versionNo", this.versionNo).append("creationTimeStamp",
				this.creationTimestamp).append("lastUpdateTimestamp",
				this.lastUpdateTimestamp).toString();
	}

}
